package by.amakarevich.dataaccess.Impl;

import java.util.List;

import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.SingularAttribute;

import org.apache.commons.lang3.Validate;
import org.hibernate.jpa.criteria.OrderImpl;
import org.springframework.stereotype.Repository;

import by.amakarevich.dataaccess.DiscountDao;
import by.amakarevich.datamodel.Discount;
import by.amakarevich.datamodel.Discount_;

@Repository
public class DiscountDaoImpl extends AbstractDaoImpl<Long, Discount> implements DiscountDao {
	protected DiscountDaoImpl(){
		super(Discount.class);
	}
	
	/*
     * 'select all' example.
     */
    @Override
    public List<Discount> getAllDiscount() {
        CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

        CriteriaQuery<Discount> criteria = cBuilder.createQuery(Discount.class);
        Root<Discount> root = criteria.from(Discount.class);

        criteria.select(root);

        TypedQuery<Discount> query = getEm().createQuery(criteria);
        List<Discount> results = query.getResultList();
        return results;
    }

    @Override
    public Long getCount() {
        CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

        CriteriaQuery<Long> criteria = cBuilder.createQuery(Long.class);
        Root<Discount> root = criteria.from(Discount.class);

        criteria.select(cBuilder.count(root));

        TypedQuery<Long> query = getEm().createQuery(criteria);
        return query.getSingleResult();
    }

    /*
     * 'select all' with sorting and paging example.
     */
    @Override
    public List<Discount> getAllDiscount(SingularAttribute<Discount, ?> attr, boolean ascending, int startRecord, int pageSize) {
        CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

        CriteriaQuery<Discount> criteria = cBuilder.createQuery(Discount.class);
        Root<Discount> root = criteria.from(Discount.class);

        criteria.select(root);
        criteria.orderBy(new OrderImpl(root.get(attr), ascending));

        TypedQuery<Discount> query = getEm().createQuery(criteria);
        query.setFirstResult(startRecord);
        query.setMaxResults(pageSize);

        List<Discount> results = query.getResultList();
        return results;
    }

    /*
     * 'select/where' example.
     */
    @Override
    public List<Discount> getAllDiscountByProduct(String name) {
        CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

        CriteriaQuery<Discount> root = cBuilder.createQuery(Discount.class);
        Root<Discount> criteria = root.from(Discount.class);

        root.select(criteria);

        root.where(cBuilder.equal(criteria.get(Discount_.name), name));

        TypedQuery<Discount> query = getEm().createQuery(root);
        List<Discount> results = query.getResultList();
        return results;
    }

    @Override
    public void updateDiscountPrice(Long id, String newName) {
        String q = String.format("update from %s p set p.name=:newNameParam where p.id=:id", Discount.class.getSimpleName());
        Query updateQuery = getEm().createQuery(q);
        updateQuery.setParameter("newNameParam", newName);
        updateQuery.setParameter("id", id);
        int updatedRowsCount = updateQuery.executeUpdate();
        Validate.isTrue(updatedRowsCount == 1, "One row should be updated");
    }
}
